package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	test "git.900sui.cn/kc/rpcPay/test/lib"
	"io/ioutil"
	"os"
	"sort"
)

func GenerateRSAKey(bits int) {
	//GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥
	//Reader是一个全局、共享的密码用强随机数生成器
	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		panic(err)
	}
	//保存私钥
	//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
	X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
	//使用pem格式对x509输出的内容进行编码
	//创建文件保存私钥
	privateFile, err := os.Create("private.pem")
	if err != nil {
		panic(err)
	}
	defer privateFile.Close()
	//构建一个pem.Block结构体对象
	privateBlock := pem.Block{Type: "RSA Private Key", Bytes: X509PrivateKey}
	//将数据保存到文件
	pem.Encode(privateFile, &privateBlock)

	//保存公钥
	//获取公钥的数据
	publicKey := privateKey.PublicKey
	//X509对公钥编码
	X509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
	if err != nil {
		panic(err)
	}
	//pem格式编码
	//创建用于保存公钥的文件
	publicFile, err := os.Create("public.pem")
	if err != nil {
		panic(err)
	}
	defer publicFile.Close()
	//创建一个pem.Block结构体对象
	publicBlock := pem.Block{Type: "RSA Public Key", Bytes: X509PublicKey}
	//保存到文件
	pem.Encode(publicFile, &publicBlock)
}

func getSHA256(signMap map[string]interface{}) (shal256Str string, err error) {
	keys := []string{}
	for k, _ := range signMap {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	strs := ""
	for _, v := range keys {
		if signMap[v] == "" {
			continue
		}
		strs += v + "=" + signMap[v].(string) + "&"
	}
	strs = strs[0 : len(strs)-1] //去掉最后一个 &
	shal256Str = Sha256(strs)    //对字符串进行sha256加密
	return shal256Str, nil
}

func sign(signMap map[string]interface{}) (sign string, err error) {
	keys := []string{}
	for k, _ := range signMap {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	strs := ""
	for _, v := range keys {
		if signMap[v] == "" {
			continue
		}
		strs += v + "=" + signMap[v].(string) + "&"
	}
	strs = strs[0 : len(strs)-1]
	fmt.Println("去掉最后一个&：", strs)
	//对字符串进行sha1哈希
	sign = Sha256(strs)
	return sign, nil
}

//Sha256加密
func Sha256(src string) string {
	m := sha256.New()
	m.Write([]byte(src))
	res := hex.EncodeToString(m.Sum(nil))
	return res
}

//RSA解密
func RSA_Decrypt(cipherText []byte, path string) []byte {
	//打开文件
	file, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	//获取文件内容
	info, _ := file.Stat()
	buf := make([]byte, info.Size())
	file.Read(buf)
	//pem解码
	block, _ := pem.Decode(buf)
	//X509解码
	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		panic(err)
	}
	//对密文进行解密
	plainText, _ := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText)
	//返回明文
	return plainText
}

//func RSA_DecryptWithKey(cipherText []byte, path string) []byte {
//	privateKey,_,_:= getPriKeyCert(path)
//	//对密文进行解密
//	plainText, _ := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText)
//	//返回明文
//	return plainText
//}

//RSA加密
func RSA_Encrypt(plainText []byte, path string) []byte {
	//打开文件
	file, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	//读取文件的内容
	info, _ := file.Stat()
	buf := make([]byte, info.Size())
	file.Read(buf)
	//pem解码
	block, _ := pem.Decode(buf)
	//x509解码

	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		panic(err)
	}
	//类型断言
	publicKey := publicKeyInterface.(*rsa.PublicKey)
	//对明文进行加密
	cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
	if err != nil {
		panic(err)
	}
	//返回密文
	return cipherText
}

//RSA加密
func RSA_EncryptWithKey(plainText []byte, path string) []byte {

	//类型断言
	publicKey,err := getPubKeyCert(path)
	fmt.Println(path)
	if err != nil {
		panic(err)
	}
	//对明文进行加密
	cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
	if err != nil {
		panic(err)
	}
	//返回密文
	return cipherText
}

func getPubKeyCert(key string) (*rsa.PublicKey, error) {
	certPEMBlock, err := ioutil.ReadFile(key)
	if err != nil {
		return nil, err
	}
	certDERBlock, _ := pem.Decode(certPEMBlock)
	if certDERBlock == nil {
		return nil, err
	}
	x509Cert, err := x509.ParseCertificate(certDERBlock.Bytes)
	if err != nil {
		return nil, err
	}
	pub := x509Cert.PublicKey.(*rsa.PublicKey)
	return pub, nil
}



func main() {
	xindalu := test.NewXindalupay("private.pem","public.pem")
	params := map[string]interface{}{
		"staff_name": "hhh",
		"client_id":  "123",
		"staff_id":   "114",
		"secret":     "aaa-999",
		"sign":       "",
		"sin":        "22",
	}



	str,_:= getSHA256(params)
	en,err  := xindalu.RSA_Encrypt([]byte(str))
	if err != nil {
		fmt.Println(err.Error())
	}
	fmt.Println("加密后为：",string(en))
	de,err := xindalu.RSA_Decrypt([]byte(en))
	if err != nil {
		fmt.Println(err.Error())
	}
	fmt.Println(string(de))

	Sign,err := xindalu.Sign(params)
	if err != nil {
		fmt.Println(err.Error())
	}
	if Sign == string(en) {
		fmt.Println("加密正确")
	}
	ce,_:= xindalu.RSA_Decrypt([]byte(Sign))
	if string(ce) == str {
		fmt.Println("解密正确")
	}


	////解密
	//plainText := RSA_DecryptWithKey(cipherText, "private.pem")
	//if string(plainText) == str {
	//	fmt.Println("解密正确")
	//}
	//fmt.Println("解密后为：", string(plainText))

}
